offsite 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4515,11 +4515,18 @@ function linkProjectMedia(cwd, file) {
4515
4515
  const full = resolveProjectFile(cwd, file);
4516
4516
  const mediaType = mediaTypes.get(path.extname(full).toLowerCase());
4517
4517
  if (mediaType === void 0) throw new Error(`${file} is not an image, video or audio file`);
4518
+ return addLink(full, mediaType, null);
4519
+ }
4520
+ function linkProjectDownload(cwd, file) {
4521
+ return addLink(resolveProjectFile(cwd, file), "application/octet-stream", path.basename(file));
4522
+ }
4523
+ function addLink(file, mediaType, download) {
4518
4524
  for (const [token, link] of mediaLinks) if (link.expiresAt <= Date.now()) mediaLinks.delete(token);
4519
4525
  const token = randomBytes(32).toString("base64url");
4520
4526
  mediaLinks.set(token, {
4521
- file: full,
4527
+ file,
4522
4528
  mediaType,
4529
+ download,
4523
4530
  expiresAt: Date.now() + MEDIA_LINK_LIFETIME
4524
4531
  });
4525
4532
  return token;
@@ -4576,6 +4583,7 @@ const DIFF_LIMIT = 8e4;
4576
4583
  const UNTRACKED_LIMIT = 100;
4577
4584
  const NEW_FILE_LIMIT = 262144;
4578
4585
  const REPO_DEPTH = 3;
4586
+ const FETCH_TIMEOUT = 6e4;
4579
4587
  const run$1 = promisify(execFile);
4580
4588
  const PULL_REQUEST_INSTRUCTIONS = `You write GitHub pull requests as Markdown.
4581
4589
 
@@ -4638,8 +4646,43 @@ async function push$1(cwd) {
4638
4646
  ]);
4639
4647
  else await git(cwd, ["push"]);
4640
4648
  } catch (error) {
4641
- throw new Error((error instanceof Error ? error.message : String(error)).split("\n").filter((line) => line.trim() !== "" && !line.startsWith("hint:") && !line.startsWith("Command failed:")).join("\n"), { cause: error });
4649
+ throw gitError(error);
4650
+ }
4651
+ }
4652
+ async function sync(cwd) {
4653
+ if ((await gitStatus(cwd)).upstream === null) {
4654
+ await push$1(cwd);
4655
+ return;
4656
+ }
4657
+ try {
4658
+ await git(cwd, ["fetch"]);
4659
+ const status = await gitStatus(cwd);
4660
+ if (status.behind > 0 && status.ahead === 0) await git(cwd, [
4661
+ "merge",
4662
+ "--ff-only",
4663
+ "@{upstream}"
4664
+ ]);
4665
+ if (status.behind > 0 && status.ahead > 0) await rebaseOnUpstream(cwd);
4666
+ } catch (error) {
4667
+ throw gitError(error);
4642
4668
  }
4669
+ if ((await gitStatus(cwd)).ahead > 0) await push$1(cwd);
4670
+ }
4671
+ async function fetchProject(cwd) {
4672
+ await Promise.all((await projectRepos(cwd)).map(async (repo) => {
4673
+ try {
4674
+ await run$1("git", ["fetch"], {
4675
+ cwd: path.join(cwd, repo),
4676
+ env: {
4677
+ ...process.env,
4678
+ GIT_TERMINAL_PROMPT: "0"
4679
+ },
4680
+ timeout: FETCH_TIMEOUT
4681
+ });
4682
+ } catch (error) {
4683
+ throw gitError(error);
4684
+ }
4685
+ }));
4643
4686
  }
4644
4687
  async function localBranches(cwd) {
4645
4688
  return (await git(cwd, [
@@ -4796,6 +4839,7 @@ async function projectRepos(cwd) {
4796
4839
  }
4797
4840
  async function gitStatus(cwd) {
4798
4841
  const output = await git(cwd, [
4842
+ "--no-optional-locks",
4799
4843
  "status",
4800
4844
  "--porcelain=v2",
4801
4845
  "--branch"
@@ -4803,6 +4847,7 @@ async function gitStatus(cwd) {
4803
4847
  const status = {
4804
4848
  branch: null,
4805
4849
  upstream: null,
4850
+ remote: (await git(cwd, ["remote"])).stdout.trim() !== "",
4806
4851
  ahead: 0,
4807
4852
  behind: 0,
4808
4853
  changed: 0
@@ -4819,6 +4864,25 @@ async function gitStatus(cwd) {
4819
4864
  }
4820
4865
  return status;
4821
4866
  }
4867
+ async function rebaseOnUpstream(cwd) {
4868
+ try {
4869
+ await git(cwd, ["rebase", "@{upstream}"]);
4870
+ } catch (error) {
4871
+ const rebasing = await git(cwd, [
4872
+ "rev-parse",
4873
+ "--git-path",
4874
+ "rebase-merge"
4875
+ ]);
4876
+ if (existsSync(path.resolve(cwd, rebasing.stdout.trim()))) {
4877
+ await git(cwd, ["rebase", "--abort"]);
4878
+ throw new Error("Your commits conflict with the remote branch, so nothing was pulled or pushed. Resolve it in a terminal.", { cause: error });
4879
+ }
4880
+ throw error;
4881
+ }
4882
+ }
4883
+ function gitError(error) {
4884
+ return new Error((error instanceof Error ? error.message : String(error)).split("\n").filter((line) => line.trim() !== "" && !line.startsWith("hint:") && !line.startsWith("Command failed:")).join("\n"), { cause: error });
4885
+ }
4822
4886
  async function isRepo(cwd) {
4823
4887
  try {
4824
4888
  await git(cwd, ["rev-parse", "--is-inside-work-tree"]);
@@ -4880,8 +4944,10 @@ function newFilePatch(cwd, file, prefix) {
4880
4944
  const name = `${prefix}${file}`;
4881
4945
  const header = `diff --git a/${name} b/${name}\nnew file\n--- /dev/null\n+++ b/${name}\n`;
4882
4946
  const full = path.join(cwd, file);
4883
- if (lstatSync(full).isSymbolicLink()) return `${header}@@ -0,0 +1 @@\n+${readlinkSync(full)}\n`;
4884
- if (statSync(full).size > NEW_FILE_LIMIT) return `${header}Binary or large file\n`;
4947
+ const stats = lstatSync(full);
4948
+ if (stats.isSymbolicLink()) return `${header}@@ -0,0 +1 @@\n+${readlinkSync(full)}\n`;
4949
+ if (stats.isDirectory()) return `${header}Nested repository\n`;
4950
+ if (stats.size > NEW_FILE_LIMIT) return `${header}Binary or large file\n`;
4885
4951
  const content = readFileSync(full, "utf8");
4886
4952
  if (content.includes("\0")) return `${header}Binary or large file\n`;
4887
4953
  const lines = content.split("\n");
@@ -6103,6 +6169,7 @@ const handlers = {
6103
6169
  "files.list": (params) => listFiles(projectPath(params.projectId)),
6104
6170
  "files.read": (params) => readProjectFile(projectPath(params.projectId), params.path),
6105
6171
  "files.media": (params) => linkProjectMedia(projectPath(params.projectId), params.path),
6172
+ "files.download": (params) => linkProjectDownload(projectPath(params.projectId), params.path),
6106
6173
  "files.upload": (params) => saveUpload(params.name, Buffer.from(params.data, "base64")),
6107
6174
  "tasks.output": (params) => taskOutput(params.sessionId, params.path),
6108
6175
  "git.status": (params) => gitRepos(projectPath(params.projectId)),
@@ -6112,6 +6179,14 @@ const handlers = {
6112
6179
  await push$1(path.join(projectPath(params.projectId), params.repo));
6113
6180
  return null;
6114
6181
  },
6182
+ "git.sync": async (params) => {
6183
+ await sync(path.join(projectPath(params.projectId), params.repo));
6184
+ return null;
6185
+ },
6186
+ "git.fetch": async (params) => {
6187
+ await fetchProject(projectPath(params.projectId));
6188
+ return null;
6189
+ },
6115
6190
  "git.branches": (params) => pullRequestBranches(path.join(projectPath(params.projectId), params.repo)),
6116
6191
  "git.localBranches": (params) => localBranches(path.join(projectPath(params.projectId), params.repo)),
6117
6192
  "git.switch": async (params) => {
@@ -6400,6 +6475,7 @@ function serveMedia(token, request, response) {
6400
6475
  return;
6401
6476
  }
6402
6477
  response.setHeader("content-type", link.mediaType);
6478
+ if (link.download !== null) response.setHeader("content-disposition", `attachment; filename*=UTF-8''${encodeURIComponent(link.download)}`);
6403
6479
  response.setHeader("accept-ranges", "bytes");
6404
6480
  response.setHeader("cache-control", "private, max-age=3600");
6405
6481
  response.setHeader("content-security-policy", "sandbox");